<template>
  <!-- <input type="string" v-model="prefixRef" /> -->
  <select v-model="prefixRef">
    <option :value="d" v-for="d of prefixsRef">{{ d }}</option>
  </select>
  <input type="string" v-model="ignoreRef" />
  <textarea v-model="textRef"></textarea>
  <highlightjs language="dart" :code="varCodeRef" />
  <highlightjs language="dart" :code="widgetRef" />
  <highlightjs language="dart" :code="codeRef + '\n\n' + styleCodeRef" />
</template>
<script setup>
import { computed, ref, watch } from 'vue';


const prefixs = [`--van-[^-]*-`, `--van-[^-]*-[^-]*-`, '--van-']

/** @type {import('vue').Ref<string>} */
const textRef = ref("");
const prefixRef = ref(prefixs[0]);
const ignoreRef = ref("large,mini,default,small,normal,primary,success,danger,warning,disabled,round,plain,medium");
const widgetRef = ref("");
const prefixsRef = ref([]);

textRef.value = ``;

const xxs = ['font', 'line', 'height', 'color', 'label', 'vertical', 'horizontal', 'left', 'right', 'top', 'bottom', 'required', 'border', 'active', 'value', 'text', 'icon', 'background'];
watch(() => textRef.value, (text) => {
  if (!text && localStorage.getItem("flutter-ui-var")) {
    textRef.value = localStorage.getItem("flutter-ui-var").replace("}", '');
    return;
  }
  text = text.replace(/;/g, '').split("\n").map(d => d.trim()).filter(d => d.length > 0).join("\n");

  const lines = text.split("\n");
  const keys = [];
  for (const line of lines) {
    const xx = line.trim().split(':')[0].split('-');
    let m = '';
    for (const d of xx) {
      m += d + '-';
      if (d && (xxs.includes(d) || ignoreRef.value.includes(d))) {
        break;
      }
      if (d && !keys.includes(m)) {
        keys.push(m);
      }
    }

  }
  prefixsRef.value = keys;
  if (text == textRef.value) return;







  textRef.value = text;
  localStorage.setItem("flutter-ui-var", text);
}, { immediate: true });

function toHump(name) {
  return name.replace(/\-(\w)/g, function (all, letter) {
    return letter.toUpperCase();
  });
}

function getType(key) {
  let type = 'String';
  if (key.includes("height") || key.includes("size") || key.includes("width")) type = "double";
  else if (key.includes('radius')) type = 'BorderRadius';
  else if (key.includes("padding") || key.includes("margin")) type = "EdgeInsets";
  else if (key.includes("opacity") || key.includes("duration")) type = "double";
  else if (key.includes("bold") || key.includes("duration")) type = "double";
  else if (key.includes("color")) type = "Color";
  else if (key.includes("background")) type = "VanBgColor";
  else type = "String";
  return type;
}

const varCodeRef = computed(() => {
  const text = textRef.value;
  if (!text) return "";
  let widget;
  const lines = text.replace(/;/g, '').split("\n");
  const str = lines.map(line => {
    let [key, value] = line.trim().split(": ");
    if (!value) return '';

    if (!widget) {
      const attr1 = key.replace(new RegExp(prefixRef.value), '').replace(/^-+/g, '')
      const attr = toHump(attr1);
      const name1 = key.substring('--van-'.length, key.length - attr1.length - 1);
      widget = toHump(`a-van-${name1}`).substring(1).replace(/-+/g, '');
    }
    value = value.trim().replace(/px$/, '');
    if (value.startsWith("#") && value.length == 7) {
      value = `const Color(0xff${value.substring(1)})`;
    } else if (value.startsWith("#") && value.length == 4) {
      const array = [
        value.substr(1, 1) + value.substr(1, 1),
        value.substr(2, 1) + value.substr(2, 1),
        value.substr(3, 1) + value.substr(3, 1)
      ];
      value = `const Color(0xff${array.join('')})`;
    } else if (value.startsWith('rgba')) {
      value = value.replace('rgba', 'Color.fromRGBO');
    }
    else if (!/^\d+$/.test(value)) value = `"${value}"`;


    return `"${key}": ${value},`
  }).join("\n");;
  return `/// [${widget}]主题样式\n` + str;
});

const styleCodeRef = computed(() => {
  const text = textRef.value;
  if (!text) return "";

  const lines = text.replace(/;/g, '').split("\n");

  const regexp = new RegExp(ignoreRef.value.split(",").join("|"));

  const exists = [];
  const declares = [];
  const props = [];
  const copys = [];
  let widget;
  let name1;
  for (const line of lines) {
    let [key, value] = line.trim().split(": ");
    key = key.replace(regexp, "");
    if (exists.includes(key)) continue;
    exists.push(key);
    const attr1 = key.replace(new RegExp(prefixRef.value), '').replace(/^-+/g, '')
    const attr = toHump(attr1);
    name1 = key.substring('--van-'.length, key.length - attr1.length - 1);
    if (!widget) widget = toHump(`a-van-${name1}`).substring(1).replace(/-+/g, '');
    if (props.includes(attr)) continue
    props.push(attr);

    const type = getType(key, value);



    declares.push(`  final ${type}? ${attr};`)
    copys.push(`    ${type}? ${attr},`)
  }
  if (!widget || widget == 'Van' || widget == "VanVan") return '';



  return [
    `/// [${widget}]样式`,
    `@immutable`,
    `class ${widget}Style with VanProvide {`,
    `  static of(BuildContext context) => VanInheritedWidget.of<${widget}Style>(context);`,
    ``,
    // `  final double? fontSize;`,
    declares.join('\n'),
    ``,
    `  ${widget}Style({`,
    // `    this.fontSize,`,
    props.map(d => `    this.${d},`).join("\n"),
    `  });`,
    ``,
    `  bool get isNonNull {`,
    // `    if (background == null) return false;`,
    props.map(d => `    if (${d} == null) return false;`).join("\n"),
    `    return true;`,
    `  }`,
    ``,
    `  ${widget}Style copyFrom({`,
    // `    VanCss<double>? fontSize`,
    // `    VanCss<double>? lineHeight`,
    copys.join("\n"),
    `  }) {`,
    `    return ${widget}Style(`,
    // `      fontSize: fontSize ?? this.fontSize,`,
    // `      lineHeight: lineHeight ?? this.lineHeight,`,
    props.map(d => `      ${d}: ${d} ?? this.${d},`).join("\n"),
    `    );`,
    `  }`,
    `}`,
  ].join("\n");
});

/** 
 * @type {import('vue').ComputedRef<string>}
 * @param {string} text
 */
const codeRef = computed(() => {
  const text = textRef.value;
  if (!text) return "";

  const lines = text.replace(/;/g, '').split("\n");

  const kvars = [];
  const gets = [];
  const attrs = [];
  const props = [];
  const jsons = [];
  const copys = [];
  let clzz;
  let widget;
  let name1;
  let name;

  const attrs2 = [];
  const props2 = [];
  const props21 = [];

  for (const line of lines) {
    const [key, value] = line.trim().split(": ");
    const k = toHump(key.replace("-", 'k'));
    kvars.push(`const ${k} = VanCssKey._raw('${key}');`);

    const regexp = new RegExp(ignoreRef.value.split(",").join("|"));
    const attr1 = key.replace(new RegExp(prefixRef.value), '')
    const attr = toHump(attr1);
    name1 = key.substring('--van-'.length, key.length - attr1.length - 1)
      .replace(/(^-+)|(-+$)/g, '');
    if (!name) name = toHump(name1).replace(/-+/g, '');
    if (!clzz) clzz = toHump(`a-van-${name1}-theme-data`).substring(1).replace(/-+/g, '');
    if (!widget) widget = toHump(`a-van-${name1}`).substring(1).replace(/-+/g, '');

    gets.push(`    if (${k} == key) return ${name || 'van'}Theme.${attr}.get(context);`)

    const type = getType(key, value);


    attrs.push(`  final VanCss<${type}> ${attr};`);
    props.push(attr);

    jsons.push(`      ${attr}: VanCss(json[${k}.key]),`);

    copys.push(`    VanCss<${type}>? ${attr},`)


    const attr2 = toHump(attr1.replace(regexp, '').replace(/^-+/, '')).replace(/-+/g, '');
    if (!attrs2.includes(attr2)) {
      attrs2.push(attr2);
      props2.push(`    ${type}? ${attr2} = style?.${attr2};`);
      const k2 = toHump('k-' + key.replace(regexp, '').replace(/^-+/, '')).replace(/-+/g, '')
      props21.push(`    ${attr2} ??= ${k2}.get(context);`);
    }

  }

  widgetRef.value = [
    `  ${widget}Style getComputedStyle(BuildContext context) {`,
    `    if (style?.isNonNull == true) return style!;`,
    props2.join('\n'),
    // `    VanBackground? background = style?.background;`,
    // `    Color? titleColor = style?.titleColor;`,
    ``,
    // `    background ??= kVanCellGroupBackground.get(context);`,
    // `    titleColor ??= kVanCellGroupTitleColor.get(context);`,
    props21.join('\n'),
    ``,
    `    return ${widget}Style(`,
    attrs2.map(d => `        ${d}: ${d},`).join("\n"),
    // `        background: background,`,
    // `        titleColor: titleColor,`,
    `    );`,
    `  }`,
  ].join("\n");

  return [

    `part of '../widgets.dart';`,
    ``,
    `/// [${widget}]属性常量\n${kvars.join("\n")}\n`,
    // 主题类
    `\n/// [${widget}]主题类`,
    `@immutable`,
    `class ${widget}Theme extends VanInheritedWidget<${widget}ThemeData> with VanProvide {`,
    `  const ${widget}Theme({super.key, required super.child, required super.data});`,
    ``,
    `  static ${widget}ThemeData of(BuildContext context) => VanInheritedWidget.of<${widget}Theme>(context)?.data ?? VanTheme.of(context).${name}Theme;`,
    `  static const _prefix = "--van-${name1 || 'root'}-";`,
    `  static bool support(VanCssKey key) => key.key.startsWith(_prefix);`,
    ``,
    `  static dynamic get<T>(BuildContext context, {required VanCssKey key, T? defaultValue}) {`,
    `    final ${widget}ThemeData ${name || 'van'}Theme = ${widget || 'Van'}Theme.of(context);`,
    // `    if (kVanCellFontSize == key) return cellTheme.fontSize.get(context);`,
    // `    if (kVanCellLineHeight == key) return cellTheme.lineHeight.get(context);`,
    gets.join("\n"),
    `    return null;`,
    `  }`,
    `}`,

    /// 主题数据类
    `\n/// [${widget}]主题数据类`,
    `@immutable\nclass ${clzz} with VanProvide {`,
    `${attrs.join("\n")}`,

    // 构造函数
    '\n  /// 构造器',
    `  const ${clzz}.raw({`,
    props.map(d => `    required this.${d},`).join("\n"),
    ` });`,

    // copyFrom
    '\n  /// 拷贝',
    `  ${clzz} copyFrom({`,
    // `    VanCss<double>? fontSize`,
    // `    VanCss<double>? lineHeight`,
    copys.join("\n"),
    `  }) {`,
    `    return ${widget}ThemeData.raw(`,
    // `      fontSize: fontSize ?? this.fontSize,`,
    // `      lineHeight: lineHeight ?? this.lineHeight,`,
    props.map(d => `      ${d}: ${d} ?? this.${d},`).join("\n"),
    `    );`,
    `  }`,

    // formJson
    '\n  /// 反序列化',
    `  static ${clzz} fromJson(Map<String, dynamic> json) {`,
    `    return ${clzz}.raw(`,
    jsons.join("\n"),
    `    );`,
    `  }`,


    // end
    `\n}`
  ].join("\n");
});





</script>